package com.talking.view

import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.content.Context
import android.graphics.Color
import android.os.Build
import android.text.Editable
import android.text.InputFilter
import android.text.InputFilter.LengthFilter
import android.text.InputType
import android.text.TextWatcher
import android.util.AttributeSet
import android.view.Gravity
import android.view.KeyEvent
import android.view.View
import android.view.View.OnFocusChangeListener
import android.widget.EditText
import android.widget.LinearLayout
import com.talking.R

class VerificationCodeView(private val mContext: Context, attrs: AttributeSet?) : LinearLayout(mContext, attrs), TextWatcher, View.OnKeyListener, OnFocusChangeListener {
    private var onCodeFinishListener: OnCodeFinishListener? = null
    /**
     * 输入框数量
     */
    private val mEtNumber = 4
    private val mEtWidth = 100
    /**
     * 文字颜色
     */
    private val mEtTextColor = Color.BLACK
    /**
     * 文字大小
     */
    private val mEtTextSize = 16f
    /**
     * 输入框背景
     */
    private val mEtTextBg = R.drawable.et_login_code_transparent
    /**
     * 输入框间距
     */
    private val mEtSpacing = 0
    /**
     * 判断是否平分
     */
    private val isBisect = false
    private var mViewWidth = 0
    fun setOnCodeFinishListener(onCodeFinishListener: OnCodeFinishListener?) {
        this.onCodeFinishListener = onCodeFinishListener
    }
    @SuppressLint("ResourceAsColor")
    private fun initView() {
        for (i in 0 until mEtNumber) {
            val editText = EditText(mContext)
            initEditText(editText, i)
            addView(editText)
            if (i == 0) editText.isFocusable = true
        }
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    private fun initEditText(editText: EditText, i: Int) {
        editText.layoutParams = getETLayoutParams(i)
        editText.textAlignment = TEXT_ALIGNMENT_CENTER
        editText.gravity = Gravity.CENTER
        editText.id = i
        editText.isCursorVisible = false
        editText.maxEms = 1
        editText.setTextColor(mEtTextColor)
        editText.textSize = mEtTextSize
        editText.maxLines = 1
        editText.filters = arrayOf<InputFilter>(LengthFilter(1))
        editText.inputType = InputType.TYPE_CLASS_NUMBER
        editText.setPadding(0, 0, 0, 0)
        editText.setOnKeyListener(this)
        editText.setBackgroundResource(mEtTextBg)
        editText.addTextChangedListener(this)
        editText.setOnKeyListener(this)
        editText.onFocusChangeListener = this
    }

    private fun getETLayoutParams(i: Int): LayoutParams {
        val layoutParams = LayoutParams(mEtWidth, mEtWidth)
        if (!isBisect) {
            val mEtBisectSpacing = (mViewWidth - mEtNumber * mEtWidth) / (mEtNumber + 1)
            when (i) {
                0 -> {
                    layoutParams.leftMargin = mEtBisectSpacing
                    layoutParams.rightMargin = mEtBisectSpacing / 2
                }
                mEtNumber - 1 -> {
                    layoutParams.leftMargin = mEtBisectSpacing / 2
                    layoutParams.rightMargin = mEtBisectSpacing
                }
                else -> {
                    layoutParams.leftMargin = mEtBisectSpacing / 2
                    layoutParams.rightMargin = mEtBisectSpacing / 2
                }
            }
        } else {
            layoutParams.leftMargin = mEtSpacing / 2
            layoutParams.rightMargin = mEtSpacing / 2
        }
        layoutParams.gravity = Gravity.CENTER
        return layoutParams
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        mViewWidth = measuredWidth
        updateETMargin()
    }

    private fun updateETMargin() {
        for (i in 0 until mEtNumber) {
            val editText = getChildAt(i) as EditText
            editText.layoutParams = getETLayoutParams(i)
        }
    }

    override fun onFocusChange(view: View, b: Boolean) {
        if (b) focus()
    }

    override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
    override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
    override fun afterTextChanged(s: Editable) {
        if (s.isNotEmpty()) focus()
        if (onCodeFinishListener != null) {
            onCodeFinishListener!!.onTextChange(this, result)
            val lastEditText = getChildAt(mEtNumber - 1) as EditText
            if (lastEditText.text.isNotEmpty()) {
                onCodeFinishListener!!.onComplete(this, result)
            }
        }
    }

    override fun onKey(v: View, keyCode: Int, event: KeyEvent): Boolean {
        if (keyCode == KeyEvent.KEYCODE_DEL && event.action == KeyEvent.ACTION_DOWN) {
            backFocus()
        }
        return false
    }

    override fun setEnabled(enabled: Boolean) {
        val childCount = childCount
        for (i in 0 until childCount) {
            val child = getChildAt(i)
            child.isEnabled = enabled
        }
    }

    private fun focus() {
        val count = childCount
        var editText: EditText
        for (i in 0 until count) {
            editText = getChildAt(i) as EditText
            if (editText.text.isEmpty()) {
                editText.requestFocus()
                return
            } else {
                editText.isCursorVisible = false
                if (i == count - 1) {
                    editText.requestFocus()
                }
            }
        }
    }

    private fun backFocus() {
        var editText: EditText
        for (i in mEtNumber - 1 downTo 0) {
            editText = getChildAt(i) as EditText
            if (editText.text.isNotEmpty()) {
                editText.setText("")
                editText.requestFocus()
                return
            }
        }
    }

    private val result: String
        get() {
            val stringBuffer = StringBuilder()
            var editText: EditText
            for (i in 0 until mEtNumber) {
                editText = getChildAt(i) as EditText
                stringBuffer.append(editText.text)
            }
            return stringBuffer.toString()
        }

    interface OnCodeFinishListener {
        fun onTextChange(view: View?, content: String?)
        fun onComplete(view: View?, content: String?)
    }

    fun setEmpty() {
        var editText: EditText
        for (i in mEtNumber - 1 downTo 0) {
            editText = getChildAt(i) as EditText
            editText.setText("")
            if (i == 0) editText.requestFocus()
        }
    }
    init {
        initView()
    }
}